package EndPoints;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * Created by hadoop on 17-6-15.
 * 端点类，用于WebSocket服务端
 */
@ServerEndpoint(value = "/chat")
public class ChatEndPoint{
    private static final String GUEST_PREFIX = "Visitor";
    private static final AtomicInteger connectionIds = new AtomicInteger(0);
    private static final Set<ChatEndPoint> clientSet = new CopyOnWriteArraySet<>();
    private final String nickname;
    private Session session;

    public ChatEndPoint(){
        nickname = GUEST_PREFIX+connectionIds.getAndIncrement();
    }

    @OnOpen
    public void start(Session session){
        System.out.println("======Start EndPoint======");
        this.session =session;
        clientSet.add(this);
        String message = String.format("[%s %s]",nickname,"gets in!");
        broadcast(message);
    }

    @OnClose
    public void end(){
        clientSet.remove(this);
        String message = String.format("[%s %s]",nickname,"gets out!");
        broadcast(message);
    }

    @OnMessage
    public void incoming(String message){
        String filteredMessage = String.format("[%s]: %s",nickname,filter(message));
        broadcast(filteredMessage);
    }

    @OnError
    public void onError(Throwable t){
        System.out.println("web socket 服务端错误");
        t.printStackTrace();
    }

    private  static String filter(String message) {
        if(message == null){
            return null;
        }
        char[] content = new char[message.length()];
        message.getChars(0,message.length(),content,0);
        StringBuilder sb = new StringBuilder(content.length+50);
        for (char aContent : content) {
            switch (aContent) {
                case '<':
                    sb.append("&lt;");
                    break;
                case '>':
                    sb.append("&gt;");
                    break;
                case '&':
                    sb.append("&amp;");
                    break;
                case '"':
                    sb.append("&quot;");
                    break;
                default:
                    sb.append(aContent);
            }
        }
        return sb.toString();
    }

    private static void broadcast(String message) {
        for(ChatEndPoint client : clientSet){
            try {
                synchronized (client){
                    client.session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                System.out.println("广播错误，发送到"+client.nickname);
                clientSet.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                String msg = String.format("[%s %s]",client.nickname,"disconnect!");
                broadcast(msg);
                e.printStackTrace();
            }
        }
    }

}
